/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sim.coalitional;

import sim.helpers.Helper;
import java.util.Collections;
import java.util.LinkedList;
import sim.helpers.comparers.NodeComparer;

/**
 *
 * @author artem
 */
public class Node {

    private int id;
    private int coalitionId;
    private double value;
    private double nonCooperativeValue;
    private double energy;
    private double radius;
    private double transmissionEnergy;
    private double distanceFromClosestHead;
    private Coordinates coor;
    private Head closestHead;
    private LinkedList<Node> neighbors;
    private Helper helper;

    public Node(int id, Coordinates coor, double radius, double energy, Helper helper) {
        this.id = id;
        this.coalitionId = id;
        this.coor = coor;
        this.radius = radius;
        this.energy = energy;
        this.neighbors = new LinkedList<Node>();
        this.helper = helper;
    }

    public Node(int id, int x, int y, double radius, double energy, Helper helper) {
        this.id = id;
        this.coalitionId = id;
        this.coor = new Coordinates(x, y);
        this.radius = radius;
        this.energy = energy;
        this.neighbors = new LinkedList<Node>();
        this.helper = helper;
    }

    public void calculateNonCooperativeValue(){
//        this.nonCooperativeValue = energy / transmissionEnergy;
        this.nonCooperativeValue = 0;
        return;
    }

    public void calculateTransmissionEnergy(){
        double constant = 5;    //For normalization purposes
        transmissionEnergy = Math.pow(distanceFromClosestHead, 2) * constant;
        return;
    }

    public void calculateDistanceFromClosestHead(){
        this.distanceFromClosestHead = helper.distance(this, closestHead);
        return;
    }

    public boolean isWithinRadius(Node n){
        if (helper.distance(this, n) <= this.radius)
            return true;
		return false;
    }

    public void addNeighbor(Node n){
        if (neighbors.contains(n))
            return;
		neighbors.add(n);
        Collections.sort(neighbors, new NodeComparer(this, helper));
        return;
    }

    public void printNeighbors(){
        System.out.print("Node " + id + " has the following neighbors:");
        for (Node node : neighbors) {
            System.out.print(" " + node.getId());
        }
        System.out.print("\n");
        return;
    }

    @Override
    public Node clone(){
        Node ret = new Node(id, getCoor(), radius, energy, this.helper);
        ret.setClosestHead(closestHead);
        ret.setCoalitionId(coalitionId);
        return ret;
    }

    //    <editor-fold defaultstate="collapsed" desc="Getters & Setters">
    /**
     * @return the id
     */
    public int getId() {
        return id;
    }

    /**
     * @param id the id to set
     */
    public void setId(int id) {
        this.id = id;
    }

    /**
     * @return the coalitionId
     */
    public int getCoalitionId() {
        return coalitionId;
    }

    /**
     * @param coalitionId the coalitionId to set
     */
    public void setCoalitionId(int coalitionId) {
        this.coalitionId = coalitionId;
    }

    /**
     * @return the value
     */
    public double getValue() {
        return value;
    }

    /**
     * @param value the value to set
     */
    public void setValue(double cooperativeValue) {
        this.value = cooperativeValue;
    }

    /**
     * @return the nonCooperativeValue
     */
    public double getNonCooperativeValue() {
        return nonCooperativeValue;
    }

    /**
     * @param nonCooperativeValue the nonCooperativeValue to set
     */
    public void setNonCooperativeValue(double nonCooperativeValue) {
        this.nonCooperativeValue = nonCooperativeValue;
    }

    /**
     * @return the energy
     */
    public double getEnergy() {
        return energy;
    }

    /**
     * @return the radius
     */
    public double getRadius() {
        return radius;
    }

    /**
     * @return the transmissionEnergy
     */
    public double getTransmissionEnergy() {
        return transmissionEnergy;
    }

    /**
     * @param transmissionEnergy the transmissionEnergy to set
     */
    public void setTransmissionEnergy(double transmissionEnergy) {
        this.transmissionEnergy = transmissionEnergy;
    }

    /**
     * @return the distanceFromClosestHead
     */
    public double getDistanceFromClosestHead() {
        return distanceFromClosestHead;
    }

    /**
     * @param distanceFromClosestHead the distanceFromClosestHead to set
     */
    public void setDistanceFromClosestHead(double distanceFromClosestHead) {
        this.distanceFromClosestHead = distanceFromClosestHead;
    }

    /**
     * @return the coor
     */
    public Coordinates getCoor() {
        return coor;
    }

    /**
     * @return the closestHead
     */
    public Head getClosestHead() {
        return closestHead;
    }

    /**
     * @param closestHead the closestHead to set
     */
    public void setClosestHead(Head closestHead) {
        this.closestHead = closestHead;
//        calculateDistanceFromClosestHead();
//        calculateTransmissionEnergy();
        calculateNonCooperativeValue();
        setValue(nonCooperativeValue);
    }

    /**
     * @return the neighbors
     */
    public LinkedList<Node> getNeighbors() {
        return neighbors;
    }

    /**
     * @param neighbors the neighbors to set
     */
    public void setNeighbors(LinkedList<Node> neighbors) {
        this.neighbors = neighbors;
    }
//</editor-fold>
}
